/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "编辑骨骼.h"

#include "Context/节点数据操作.h"





//static void f_从骨节更新编辑骨骼(S_物体* 根骨骼, S_物体** 骨节, uint32 depth, float32* 骨骼长度, const vec4& 父骨骼旋转, const float32 父骨骼长度) {
//	//vec3 s = 骨节[骨骼->m_实例ID]->m_变换.location;
//	uint32 num = 根骨骼->m_子物体.size();
//	float32 最大长度 = 0;
//
//	for (uint32 i = 0; i < num; ++i) {
//		S_物体* 骨骼 = 根骨骼->m_子物体[i];
//		S_物体* 当前开始骨节;
//
//		vec3 e = f_从骨头取末端骨节(骨骼)->m_变换.location;
//		if (depth) {
//			当前开始骨节 = f_从骨头取前端骨节(骨骼);
//		}
//		else {
//			//s = 骨节[0]->m_变换.location;
//			当前开始骨节 = 骨节[0];
//		}
//		vec3 s = 当前开始骨节->m_变换.location;
//		vec3 骨骼方向 = e - s;
//
//
//
//		float32 两骨节距离 = vec_normalize(&骨骼方向);
//		骨骼长度[骨骼->m_实例ID] = 两骨节距离;
//
//		最大长度 = DEF_Max(当前开始骨节->m_变换.scale.x, 两骨节距离);
//		当前开始骨节->f_set缩放({ 最大长度, 最大长度, 最大长度 }, 0);
//
//
//
//
//		骨骼方向 = f_graph_quat变换坐标(f_graph_quat反向(父骨骼旋转), 骨骼方向);
//		vec4 q = f_graph_quat两向量(骨骼方向, { 0, 0, 1 });
//		vec3 rot = f_graph_四元数转欧拉角(q);
//
//		rot = vec3{ -rot.x, -rot.y, rot.z };
//		if (depth) {
//			骨骼->f_set位置({ 0, 0, 父骨骼长度 }, 0);
//		}
//		else {
//			骨骼->f_set位置(s, 0);
//		}
//
//
//		骨骼->f_set旋转(rot, 0);
//		骨骼->f_set缩放({ 1 ,1 ,1 }, 0);
//		//两骨节距离 += 父骨骼长度;
//		//骨骼方向 = f_graph_quat变换坐标(q, 骨骼方向);
//		vec4 newQuat = f_graph_quatNormalize(f_graph_quat相乘(q, 父骨骼旋转));
//
//		//骨骼->m_子物体[i]->f_set位置(骨骼->f_get位置() + vec3{ 0, 0, 1 }, 0);
//		f_从骨节更新编辑骨骼(骨骼, 骨节, depth + 1, 骨骼长度, newQuat, 两骨节距离);
//	}
//}


static void f_将超出长度范围的骨节移动到范围内(S_物体* 根骨骼, S_物体** 骨节, uint32 depth, const float32* 骨骼长度, const vec3 移动修正) {
	uint32 num = 根骨骼->m_子物体.size();
	for (uint32 i = 0; i < num; ++i) {
		S_物体* 骨骼 = (S_物体*)根骨骼->m_子物体[i];
		S_物体* 当前开始骨节;

		vec3 e = f_从骨头取末端骨节(骨骼)->m_变换.position;
		if (depth) {
			当前开始骨节 = f_从骨头取前端骨节(骨骼);
		}
		else {
			//s = 骨节[0]->m_变换.location;
			当前开始骨节 = 骨节[0];
		}
		vec3 s = 当前开始骨节->m_变换.position;
		vec3 骨骼方向 = e - s;
		float32 两骨节距离 = vec_normalize(&骨骼方向);

		if (两骨节距离 > 骨骼长度[骨骼->m_实例ID] || 两骨节距离 < 骨骼长度[骨骼->m_实例ID]) {
			vec_mul(&骨骼方向, 两骨节距离 - 骨骼长度[骨骼->m_实例ID]);
			vec_sub(&(f_从骨头取末端骨节(骨骼)->m_变换.position), 骨骼方向);
			f_从骨头取末端骨节(骨骼)->m_isUpdate = true;
		}
		else {
			骨骼方向 = {};
		}

		f_将超出长度范围的骨节移动到范围内(骨骼, 骨节, depth + 1, 骨骼长度, 移动修正 + 骨骼方向);
	}
}


static vec3 f_将超出长度范围的骨节移动到范围内(S_物体* 当前骨骼, S_物体* 修正骨节, vec3& s, vec3& e, const float32* 骨骼长度) {
	vec3 骨骼方向 = e - s;
	float32 两骨节距离 = vec_normalize(&骨骼方向);

	if (两骨节距离 > 骨骼长度[当前骨骼->m_实例ID] || 两骨节距离 < 骨骼长度[当前骨骼->m_实例ID]) {
		vec_mul(&骨骼方向, 两骨节距离 - 骨骼长度[当前骨骼->m_实例ID]);
		vec_sub(&(修正骨节->m_变换.position), 骨骼方向);
		修正骨节->m_isUpdate = true;
	}
	else {
		骨骼方向 = {};
	}

	return 骨骼方向;
}
static void f_骨节更新子集骨骼(S_物体* 当前骨骼, uint32 depth, const float32* 骨骼长度, const vec3 移动修正) {
	//S_物体* 当前骨骼 = (S_物体*)当前骨节->m_UserData;
	if (当前骨骼->m_Type == E_物体类型::t_骨架) {
		uint32 num = 当前骨骼->m_子物体.size();
		for (uint32 i = 0; i < num; ++i) {
			f_骨节更新子集骨骼((S_物体*)当前骨骼->m_子物体[i], depth + 1, 骨骼长度, 移动修正);
		}
	}
	else {
		vec3 骨骼方向 = {};
		if (depth) {
			vec3 s = f_从骨头取前端骨节(当前骨骼)->m_变换.position;
			vec3 e = f_从骨头取末端骨节(当前骨骼)->m_变换.position;

			骨骼方向 = f_将超出长度范围的骨节移动到范围内(当前骨骼, f_从骨头取末端骨节(当前骨骼), s, e, 骨骼长度);
		}
		

		uint32 num = 当前骨骼->m_子物体.size();
		for (uint32 i = 0; i < num; ++i) {
			f_骨节更新子集骨骼((S_物体*)当前骨骼->m_子物体[i], depth + 1, 骨骼长度, 移动修正 + 骨骼方向);
		}
	}

	
}
static void f_骨节更新父集骨骼(S_物体* 当前骨骼, uint32 depth, const float32* 骨骼长度, const vec3 移动修正) {
	//S_物体* 当前骨骼 = ((S_物体*)(当前骨节->m_UserData))->m_父物体;
	//S_物体* 当前骨骼 = ((S_物体*)(当前骨节->m_UserData));
	if (当前骨骼->m_Type != E_物体类型::t_骨骼) {
		return;
	}


	vec3 s = f_从骨头取末端骨节(当前骨骼)->m_变换.position;
	vec3 e = f_从骨头取前端骨节(当前骨骼)->m_变换.position;

	vec3 骨骼方向 = f_将超出长度范围的骨节移动到范围内(当前骨骼, f_从骨头取前端骨节(当前骨骼), s, e, 骨骼长度);

	if (当前骨骼->m_父对象) {
		f_骨节更新父集骨骼((S_物体*)当前骨骼->m_父对象, depth + 1, 骨骼长度, 移动修正 + 骨骼方向);

		if (当前骨骼->m_父对象->m_子物体.size() > 1) {
			for (auto& 骨骼物体 : 当前骨骼->m_父对象->m_子物体) {
				if (骨骼物体 != 当前骨骼) {
					f_骨节更新子集骨骼(f_从骨头取前端骨节((S_物体*)骨骼物体), depth + 1, 骨骼长度, 移动修正 + 骨骼方向);
				}
			}
		}
	}
}

static void f_移动骨节更新骨骼(S_物体* 当前骨骼, uint32 depth, const float32* 骨骼长度, const vec3 移动修正) {
	//递归到子集
	f_骨节更新子集骨骼(当前骨骼, 0, 骨骼长度, 移动修正);

	//递归到父级
	f_骨节更新父集骨骼(当前骨骼, 0, 骨骼长度, 移动修正);
}

static void f_旋转骨节更新骨骼(S_物体* 当前骨骼, uint32 depth, const float32* 骨骼长度, const vec3 移动修正) {
	vec3 s = f_从骨头取前端骨节(当前骨骼)->m_变换.position;
	vec3 e = f_从骨头取末端骨节(当前骨骼)->m_变换.position;

	vec3 骨骼方向 = f_将超出长度范围的骨节移动到范围内(当前骨骼, f_从骨头取末端骨节(当前骨骼), s, e, 骨骼长度);

	for (auto& 骨骼物体 : 当前骨骼->m_子物体) {

	}
}





void f_BE_从骨节更新骨骼(S_物体* 骨) {
	//float32* 骨骼长度 = nullptr;
	//S_物体* 骨骼 = 骨;
	//if (骨->m_Type == E_物体类型::t_骨骼) {
	//
	//}
	//else {
	//	骨骼 = ((S_物体*)(骨->m_UserData));
	//}
	//if (!骨骼 || !骨骼->m_骨架) return;
	//
	//
	//骨骼长度 = f_buf_F32_ptr(骨骼->m_骨架->m_骨骼长度);
	//
	//switch (f_prop_enum(S_节点数据状态::g_骨架编辑模式)) {
	//	case E_骨骼编辑模式::e_骨架模式: {
	//		break;
	//	}
	//
	//	case E_骨骼编辑模式::e_编辑模式: {
	//		switch (f_prop_enum(S_节点数据状态::g_骨架编辑模式)) {
	//		case E_骨骼姿态编辑模式::e_旋转模式:
	//			f_旋转骨节更新骨骼(骨骼, 0, 骨骼长度, {});
	//			break;
	//		case E_骨骼姿态编辑模式::e_拖拽模式:
	//			f_移动骨节更新骨骼(骨骼, 0, 骨骼长度, {});
	//			break;
	//		}
	//		break;
	//	}
	//
	//	case E_骨骼编辑模式::e_姿态模式: {
	//		switch (f_prop_enum(S_节点数据状态::g_骨架编辑模式)) {
	//			case E_骨骼姿态编辑模式::e_旋转模式:
	//				f_旋转骨节更新骨骼(骨骼, 0, 骨骼长度, {});
	//				break;
	//			case E_骨骼姿态编辑模式::e_拖拽模式:
	//				f_移动骨节更新骨骼(骨骼, 0, 骨骼长度, {});
	//				break;
	//		}
	//		break;
	//	}
	//}
	
}


void f_BE_从骨骼更新骨节(S_物体* 骨) {
	float32* 骨骼长度 = nullptr;
	S_物体* 骨骼 = 骨;
	if (骨->m_Type == E_物体类型::t_骨骼) {

	}
	else {
		骨骼 = ((S_物体*)(骨->m_UserData));
	}


	switch (f_prop_enum(S_节点数据状态::g_骨架编辑模式)) {
	case E_骨骼编辑模式::e_骨架模式: {
		break;
	}

	case E_骨骼编辑模式::e_编辑模式:
		//f_旋转骨节更新骨骼(骨骼, 0, 骨骼长度, {});
		break;
	case E_骨骼编辑模式::e_姿态模式: {
		break;
	}
	}

}






//static vec3 f_设置骨节(S_物体* 骨骼, std::vector<S_物体*>& 骨节, std::vector<float32>& 骨节长度, const vec3& 父坐标, const vec4& q) {
//	S_骨骼* 骨骼对象 = f_ob_from骨骼(骨骼);
//	
//	f_ob_setPos(骨骼对象->m_骨节B, 父坐标);
//
//	骨骼->m_ID = 骨节长度.size();
//	骨节长度.push_back(骨骼对象->m_长度);
//
//	if (骨节.size() <= 骨骼->m_ID) {
//		骨节.push_back(骨骼对象->m_骨节B);
//	}
//	else {
//		骨节[骨骼->m_ID] = 骨骼对象->m_骨节B;
//	}
//
//	return {};
//}


void f_BE_构建骨架骨骼邻接属性(S_物体* 骨骼物体, int32 父骨骼, S_骨架* 骨架) {
	if (骨骼物体->m_Type != E_物体类型::t_骨骼) return;

	uint32 num = 骨骼物体->m_子物体.size();
	骨骼物体->m_骨架 = 骨架;

	S_骨骼邻接* 骨骼邻接 = (S_骨骼邻接*)malloc(sizeof(S_骨骼邻接));
	骨骼邻接->m_父骨骼ID = 父骨骼;
	骨骼邻接->m_子骨骼 = (S_I32Array*)f_core_array_new(num, sizeof(int32));
	f_core_array_push_back((S_Array*)骨架->m_骨骼邻接, (uint8*)&骨骼邻接);

	
	//S_骨骼* 当前父骨骼 = f_ob_from骨骼(骨骼物体);
	int32 当前父骨骼 = 骨骼物体->m_ID;

	for (uint32 i=0; i<num; ++i) {
		auto& 骨骼 = 骨骼物体->m_子物体[i];

		//S_骨骼* 骨骼 = f_ob_from骨骼(骨骼物体->m_子物体[i]);
		骨骼邻接->m_子骨骼->ptr_userData[i] = 骨骼->m_ID;
		//f_core_array_push_back((S_Array*)骨骼邻接->m_子骨骼, (uint8*)&骨骼);
		f_BE_构建骨架骨骼邻接属性((S_物体*)骨骼物体->m_子物体[i], 当前父骨骼, 骨架);
	}

	//S_骨骼* 当前父骨骼 = f_ob_from骨骼(骨骼物体);
	//for (auto& e : 骨骼物体->m_子物体) {
	//	f_BE_构建骨架骨骼邻接属性(e, 当前父骨骼, 骨架);
	//}
}

void f_BE_销毁骨架骨骼邻接属性(S_骨架* 骨架) {
	for (uint32 i = 0; i < 骨架->m_骨骼邻接->count; ++i) {
		f_core_array_free((S_Array*)骨架->m_骨骼邻接->ptr_userData[i]->m_子骨骼);
	}
	f_core_array_reserve((S_Array*)骨架->m_骨骼邻接, 0);
}



static void f_构建骨节坐标(S_骨架* 骨架
					, S_物体* 骨骼
					, std::vector<S_Object*>& 骨节
					, std::vector<float32>& 骨节长度
					, std::vector<vec3>& 骨骼方向
					, const vec3& 父坐标
					, const vec4& q
					, const S_物体* 对称物体
					) {

	if (骨骼->m_Type != E_物体类型::t_骨骼) return;

	S_骨骼* 骨骼对象 = f_ob_from骨骼(骨骼);
	S_骨节* 骨节对象 = f_ob_from骨节(骨骼对象);
	//骨骼对象->m_骨架 = 骨架;
	骨骼对象->m_变换后根坐标 = 父坐标;
	骨骼对象->m_初始头坐标 = 父坐标;
	//骨骼对象->m_对称物体 = nullptr;
	//骨骼对象->m_对称偏移 = {};
	//骨骼对象->m_对称方向 = -1;

	vec3 偏移 = f_ob_骨骼初始方向(骨骼对象->m_长度);

	if (!对称物体 || 骨骼对象->m_对称物体) {
		对称物体 = 骨骼对象->m_对称物体;
	}

	vec4 q_a = f_graph_quat相乘(骨骼对象->m_旋转, q);
	vec3 骨节坐标 = f_graph_quatTranformInv(q_a, 偏移);
	//vec3 骨节坐标 = 骨节对象->m_骨节初始根坐标;
	骨节坐标 += 父坐标;

	骨骼->m_变换.position = 父坐标;
	骨骼->m_ID = 骨节长度.size();


	f_ob_setLoc(骨骼对象->m_骨节B, 骨节坐标);
	骨节对象->m_骨节初始尾坐标 = 骨节坐标;



	骨节长度.push_back(骨骼对象->m_长度);
	骨骼方向.push_back(normalize(骨节坐标 - 父坐标));
	if (骨节.size() <= 骨骼->m_ID) {
		骨节.push_back(骨骼对象->m_骨节B);
	}
	else {
		骨节[骨骼->m_ID] = 骨骼对象->m_骨节B;
	}
	
	

	//uint32 骨骼数量 = 1;
	//f_设置骨节(骨骼, 骨节, 骨节长度, 骨节坐标, q_a);
	for (auto& e : 骨骼->m_子物体) {
		f_构建骨节坐标(骨架, (S_物体*)e, 骨节, 骨节长度, 骨骼方向, 骨节坐标, q_a, 对称物体);
	}

	//std::vector<uint32> 带对称骨骼索引;
	//uint32 num = 骨骼->m_子物体.size();
	//for (uint32 i = 0; i < num; ++i) {
	//	auto& e = 骨骼->m_子物体[i];
	//	S_骨骼* 骨骼对象 = f_ob_from骨骼(骨骼);
	//
	//	if (骨骼对象->m_对称物体) {
	//		带对称骨骼索引.push_back(i);
	//	}
	//	else {
	//		f_构建骨节坐标(骨架, e, 骨节, 骨节长度, 骨骼方向, 骨节坐标, q_a, 对称物体);
	//	}
	//}
	//for (auto& index : 带对称骨骼索引) {
	//	auto& e = 骨骼->m_子物体[index];
	//
	//	S_骨骼* 骨骼对象 = f_ob_from骨骼(骨骼);
	//	f_构建骨节坐标(骨架, e, 骨节, 骨节长度, 骨骼方向, 骨节坐标, q_a, 对称物体);
	//	//f_node_BE_对称骨骼(e, 父坐标, {});
	//}
	
	骨架->m_骨头数量 += 骨骼->m_子物体.size();
}


void f_OE_构建骨骼(S_物体* 骨架物体, S_物体* 骨节) {
	std::vector<float32> 骨节长度;
	std::vector<vec3> 骨骼方向;

	S_骨架* 骨架 = f_ob_from骨架(骨架物体);
	f_BE_销毁骨架骨骼邻接属性(骨架);


	骨架->m_骨头数量 = 0;
	for (auto& e : 骨架物体->m_子物体) {
		f_构建骨节坐标(骨架, (S_物体*)e, 骨节->m_子物体, 骨节长度, 骨骼方向, ((S_物体*)e)->m_变换.position, {0,0,0,1}, nullptr);
	}
	
	骨架->m_骨节数量 = 骨节长度.size();
	
	f_ob_set实例数量(骨节, 骨架->m_骨节数量);
	f_ob_fill实例ID(骨节);

	if(!骨架->m_骨节数量) return;


	//f_node_BE_更新骨节姿态(骨架, 骨节, 骨骼方向);
	f_bm_resize(骨架->m_姿态, 骨架->m_骨节数量);
	S_BonePose* 骨骼姿态 = f_buf_骨骼姿态_ptr(骨架->m_姿态);


	for (uint32 i = 0; i < 骨架->m_骨节数量; ++i) {
		S_物体* 骨节物体 = (S_物体*)骨节->m_子物体[i];

		vec3 scal = { DEF_Max(骨节长度[i], 1) };
		scal.y = scal.x;
		scal.z = scal.x;
		f_ob_setScale(骨节物体, scal * 1.1);

		auto* 骨节 = f_ob_from骨节(骨节物体);

		//骨节
		//骨骼姿态[i].tranformBoneA = _Vec4(骨节物体->m_变换.location, 骨节长度[i]);
		骨骼姿态[i].tranformBoneA = _Vec4(骨节->m_骨节初始尾坐标, 骨节长度[i]);
		骨骼姿态[i].tranformBoneB.w = 骨节->m_封套大小;
		骨骼姿态[i].dir = 骨骼方向[i];
	}


	
	for (auto& e : 骨架物体->m_子物体) {
		f_BE_构建骨架骨骼邻接属性((S_物体*)e, -1, 骨架);
	}
}

void f_OE_编辑骨节变换生成(S_物体* 骨节物体) {
	uint32 num = 骨节物体->m_子物体.size();
	auto* 骨节 = 骨节物体->m_子物体.data();

	for (uint32 i = 0; i < num; ++i) {
		//f_ob_from骨节(骨节[i])->m_骨节根坐标 = 骨节[i]->m_变换.location;
	}
}







void f_node_BE_从骨节设置骨骼(S_物体* 根骨骼, S_物体* 骨节, const vec4& 父骨骼旋转, const float32 父骨骼长度) {
	//std::cout<< 骨节->m_子物体[根骨骼->m_ID]->m_变换.location.x<<std::endl;
	uint32 num = 根骨骼->m_子物体.size();
	S_骨骼* 骨骼 = f_ob_from骨骼(根骨骼);

	vec3 s = 骨骼->m_骨节B->m_变换.position;
	//vec3 s = f_ob_from骨节(骨骼)->m_骨节坐标;
	根骨骼->m_isUpdate = true;

	for (uint32 i = 0; i < num; ++i) {
		S_物体* 末端骨骼 = (S_物体*)根骨骼->m_子物体[i];
		if (末端骨骼->m_Type != E_物体类型::t_骨骼) continue;


		S_骨骼* 骨骼数据 = f_ob_from骨骼(末端骨骼);
		vec3 e = 骨骼数据->m_骨节B->m_变换.position;

		vec3 骨骼方向 = e - s;

		骨骼数据->m_初始头坐标 = s;
		骨骼数据->m_长度 = vec_normalize(&骨骼方向);
		骨骼数据->m_方向 = 骨骼方向;
		骨骼方向 = f_graph_quatTranformInv(f_graph_quat反向(父骨骼旋转), 骨骼方向);
		
		vec4 q = f_graph_quat两向量(骨骼方向, DEF_骨骼朝向 + vec3{ 0.000000001f, 0.000000001f, 0 });
		vec3 rot = f_graph_四元数转欧拉角(q);

		rot = vec3{ -rot.x, -rot.y, rot.z };
		末端骨骼->f_set旋转(rot, 0);
		末端骨骼->f_set缩放({ 1, 1 ,1 }, 0);
		骨骼数据->m_动态旋转 = 骨骼数据->m_旋转 = q;
		


		vec4 newQuat = f_graph_quatNormalize(f_graph_quat相乘(q, 父骨骼旋转));
		f_node_BE_从骨节设置骨骼(末端骨骼, 骨节, newQuat, 骨骼数据->m_长度);

		
		for (uint32 k = 0; k < 4; ++k) {
			auto& t = f_ob_get网格变换属性(末端骨骼, k, 0);
			t.m_Scale = 骨骼数据->m_长度;
		}
		f_ob_setScale(骨节, { 骨骼数据->m_长度, 骨骼数据->m_长度, 骨骼数据->m_长度 }, 末端骨骼->m_ID);
	}

}

void f_node_BE_从骨节设置骨骼(S_物体* 骨架) {
	assert(骨架->m_Type == E_物体类型::t_骨架);

	S_物体* 骨节 = nullptr;
	for (auto& 根骨骼 : 骨架->m_子物体) {
		if ( ((S_物体*)根骨骼)->m_Type == E_物体类型::t_骨节 ) {
			骨节 = (S_物体*)根骨骼;
			break;
		}
	}

	for (auto& 根骨骼 : 骨架->m_子物体) {
		if (((S_物体*)根骨骼)->m_Type == E_物体类型::t_骨骼) {
			vec3 起点位置 = ((S_物体*)骨节->m_子物体[根骨骼->m_ID])->m_变换.position;
			f_ob_setLoc((S_物体*)根骨骼, 起点位置);
			f_node_BE_从骨节设置骨骼((S_物体*)根骨骼, 骨节, { 0,0,0,1 }, 0);

			f_node_BE_对称骨骼((S_物体*)根骨骼, 起点位置, {});
			f_node_BE_对称骨骼((S_物体*)根骨骼, 骨节, { 0,0,0,1 }, 0);
		}
	}
}



vec3 f_node_BE_对称骨骼(S_物体* 当前骨骼, const vec3& s, const vec3& 中心坐标) {
	S_骨骼* 骨骼数据 = f_ob_from骨骼(当前骨骼);
	
	
	vec3 骨骼方向;// = 骨骼数据->m_骨节B->m_变换.location - s;

	if (骨骼数据->m_对称物体) {
		S_骨骼* 对称骨骼 = f_ob_from骨骼(骨骼数据->m_对称物体);

		骨骼方向 = 对称骨骼->m_骨节B->m_变换.position - s;
		switch (骨骼数据->m_对称方向) {
			case 0: {
				骨骼方向.x = 中心坐标.x + (中心坐标.x - 骨骼方向.x);
				break;
			}
			case 1: {
				骨骼方向.y = 中心坐标.y + (中心坐标.y - 骨骼方向.y);
				break;
			}
			case 2: {
				骨骼方向.z = 中心坐标.z + (中心坐标.z - 骨骼方向.z);
				break;
			}
		}
	}
	else {
		骨骼方向 = 骨骼数据->m_骨节B->m_变换.position - s;
	}
	return 骨骼方向;
	//return 骨骼方向 + s;
}

void f_node_BE_对称骨骼(S_物体* 根骨骼, S_物体* 骨节, const vec4& 父骨骼旋转, const float32 父骨骼长度) {
	uint32 num = 根骨骼->m_子物体.size();
	S_骨骼* 骨骼 = f_ob_from骨骼(根骨骼);

	//vec3 s = f_ob_from骨节(骨骼)->m_骨节初始根坐标;
	vec3 s;
	if (骨骼->m_对称物体) {
		s = f_ob_from骨骼(骨骼->m_对称物体)->m_骨节B->m_变换.position;
	}
	else {
		s = 骨骼->m_骨节B->m_变换.position;
	}
	

	std::vector<uint32> 带对称骨骼索引;

	for (uint32 i = 0; i < num; ++i) {
		S_物体* 末端骨骼 = (S_物体*)根骨骼->m_子物体[i];
		if (末端骨骼->m_Type != E_物体类型::t_骨骼) continue;

		S_骨骼* 骨骼数据 = f_ob_from骨骼(末端骨骼);

		
		
		//if (骨骼数据->m_对称物体) {
		vec3 骨骼方向 = f_node_BE_对称骨骼(末端骨骼, s, {});
		vec3 e = 骨骼方向 + 骨骼->m_骨节B->m_变换.position;


		f_ob_setLoc(骨骼数据->m_骨节B, e);
		f_ob_from骨节(骨骼数据)->m_骨节初始尾坐标 = e;


		骨骼数据->m_初始头坐标 = 骨骼->m_骨节B->m_变换.position;
		骨骼数据->m_长度 = vec_normalize(&骨骼方向);
		骨骼数据->m_方向 = 骨骼方向;

		骨骼方向 = f_graph_quatTranformInv(f_graph_quat反向(父骨骼旋转), 骨骼方向);
		vec4 q = f_graph_quat两向量(骨骼方向, DEF_骨骼朝向 + vec3{0.000000001f, 0.000000001f, 0});
		vec3 rot = f_graph_四元数转欧拉角(q);


		rot = vec3{ -rot.x, -rot.y, rot.z };
		末端骨骼->f_set旋转(rot, 0);
		末端骨骼->f_set缩放({ 1, 1 ,1 }, 0);
		骨骼数据->m_动态旋转 = 骨骼数据->m_旋转 = q;
		

		//f_ob_from骨节(骨骼数据)->m_骨节初始根坐标 = s;
		vec4 newQuat = f_graph_quatNormalize(f_graph_quat相乘(q, 父骨骼旋转));
		f_node_BE_对称骨骼(末端骨骼, 骨节, newQuat, 骨骼数据->m_长度);
		//}
	}
}

void f_node_BE_对称骨架(S_物体* 骨架) {
	assert(骨架->m_Type == E_物体类型::t_骨架);

	S_物体* 骨节 = nullptr;
	for (auto& 根骨骼 : 骨架->m_子物体) {
		if (((S_物体*)根骨骼)->m_Type == E_物体类型::t_骨节) {
			骨节 = (S_物体*)根骨骼;
			break;
		}
	}

	for (auto& 根骨骼 : 骨架->m_子物体) {
		if (((S_物体*)根骨骼)->m_Type == E_物体类型::t_骨骼) {
			vec3 起点位置 = ((S_物体*)骨节->m_子物体[根骨骼->m_ID])->m_变换.position;

			f_node_BE_对称骨骼((S_物体*)根骨骼, 起点位置, {});
			f_node_BE_对称骨骼((S_物体*)根骨骼, 骨节, { 0,0,0,1 }, 0);
		}
	}
}



void f_node_BE_从骨节更新骨骼(S_物体* 骨架) {
	S_物体* 骨节;

	for (auto& 根骨骼 : 骨架->m_子物体) {
		if (((S_物体*)根骨骼)->m_Type == E_物体类型::t_骨节) {
			骨节 = (S_物体*)根骨骼;
			break;
		}
	}
	assert(骨节);


	for (auto& 根骨骼 : 骨架->m_子物体) {
		if (((S_物体*)根骨骼)->m_Type == E_物体类型::t_骨骼) {
			vec3 起点位置 = ((S_物体*)骨节->m_子物体[根骨骼->m_ID])->m_变换.position;
			f_ob_setLoc((S_物体*)根骨骼, 起点位置);
			f_node_BE_从骨节设置骨骼((S_物体*)根骨骼, 骨节, { 0,0,0,1 }, 0);
			//std::cout << 骨节->m_子物体[根骨骼->m_ID]->m_变换.location.x << std::endl;


			vec3 对称位置 = 起点位置;
			auto* 骨骼 = f_ob_from骨骼((S_物体*)根骨骼);
			if (骨骼->m_对称物体) {
				对称位置 = 骨骼->m_对称物体->m_变换.position;

				起点位置 = f_node_BE_对称骨骼((S_物体*)根骨骼, {}, {});

				f_ob_setLoc((S_物体*)根骨骼, 起点位置);
				f_ob_setLoc(骨骼->m_骨节B, 起点位置);
				f_ob_from骨节(骨骼)->m_骨节初始尾坐标 = 起点位置;
			}

			f_node_BE_对称骨骼((S_物体*)根骨骼, 骨节, { 0,0,0,1 }, 0);
		}
	}
}



static void f_node_更新骨骼网格属性(S_物体* 根骨骼, S_物体* 骨节) {
	uint32 num = 根骨骼->m_子物体.size();

	for (uint32 i = 0; i < num; ++i) {
		S_物体* 骨骼物体 = (S_物体*)根骨骼->m_子物体[i];
		if (骨骼物体->m_Type != E_物体类型::t_骨骼) continue;

		S_骨骼* 骨骼数据 = f_ob_from骨骼(骨骼物体);

		for (uint32 k = 0; k < 4; ++k) {
			auto& t = f_ob_get网格变换属性(骨骼物体, k, 0);
			t.m_Scale = 骨骼数据->m_长度;
		}
		f_ob_setScale(骨节, { 骨骼数据->m_长度, 骨骼数据->m_长度, 骨骼数据->m_长度 }, 骨骼物体->m_ID);
		f_mesh_计算包围盒(f_ob_getMesh(骨骼物体, 2));

		f_node_更新骨骼网格属性(骨骼物体, 骨节);
	}
}

void f_node_BE_更新骨骼网格属性(S_物体* 骨架) {
	uint32 num = 骨架->m_子物体.size();

	if (num > 1) {
		auto* 骨节 = (S_物体*)(骨架->m_子物体.back());

		for (auto& 根骨骼 : 骨架->m_子物体) {
			if (((S_物体*)根骨骼)->m_Type == E_物体类型::t_骨骼) {
				f_node_更新骨骼网格属性((S_物体*)根骨骼, 骨节);
			}
		}
	}
}




static void f_node_设置骨骼绘制模式(S_物体* 骨骼) {
	uint32 num = 骨骼->m_子物体.size();

	for (uint32 i = 0; i < num; ++i) {
		S_物体* 骨骼物体 = (S_物体*)骨骼->m_子物体[i];
		
		f_node_设置骨骼绘制模式(骨骼物体);
	}
}

void f_node_BE_设置骨骼绘制模式(S_物体* 骨架) {
	uint32 num = 骨架->m_子物体.size();

	if (num > 1) {
		auto& 骨节 = 骨架->m_子物体.back();

		for (auto& 根骨骼 : 骨架->m_子物体) {
			if (((S_物体*)根骨骼)->m_Type == E_物体类型::t_骨骼) {
				f_node_设置骨骼绘制模式((S_物体*)根骨骼);
			}
		}
	}
}

void f_node_BE_get骨骼IK(std::vector<S_骨骼IK*>& IK, S_物体* 骨骼) {
	for (auto& e : 骨骼->m_子物体) {
		if (((S_物体*)e)->m_Type == E_物体类型::t_骨骼) {
			auto ik = f_ob_from骨骼((S_物体*)e)->m_IK;
			if (ik) {
				IK.push_back(ik);
			}

			f_node_BE_get骨骼IK(IK, (S_物体*)e);
		}
	}
}














//void f_node_BE_更新骨节姿态(S_骨架* 骨架, S_物体* 骨节, const std::vector<vec3>& 骨骼方向) {
//	f_gbuf_resize(骨架->m_姿态, 骨架->m_骨节数量);
//	S_BonePose* 骨骼姿态 = f_buf_骨骼姿态_ptr(骨架->m_姿态);
//
//
//	for (uint32 i = 0; i < 骨架->m_骨节数量; ++i) {
//		S_物体* 骨节物体 = 骨节->m_子物体[i];
//
//		vec3 scal = { DEF_Max(骨节长度[i], 1) };
//		scal.y = scal.x;
//		scal.z = scal.x;
//		f_ob_setScale(骨节物体, scal * 1.1);
//
//		//骨骼姿态[i].tranformBoneA = _Vec4(骨节物体->m_变换.location, 骨节长度[i]);
//		骨骼姿态[i].tranformBoneA = _Vec4(f_ob_from骨节(骨节物体)->m_骨节初始尾坐标, 骨节长度[i]);
//		骨骼姿态[i].tranformBoneB.w = f_ob_from骨节(骨节物体)->m_封套大小;
//		骨骼姿态[i].dir = 骨骼方向[i];
//	}
//}
